#include "rkrga.h"

#include <cstring>
#include <iostream>
#include <rga/RgaUtils.h>

using namespace lsy;

int RKRga::process(std::string &srcBuf, std::string &dstBuf, const std::pair<int32_t, int32_t> &inputSize, const std::pair<int32_t, int32_t> &outputSize, const std::pair<int32_t, int32_t> &startPoint, bool scale)
{
    int ret = 0;
    int srcBufSize, dstBufSize;
    int mFirst = outputSize.first;
    int mSecond = outputSize.second;
    rga_buffer_t srcImg, dstImg;
    rga_buffer_handle_t srcHandle, dstHandle;
    im_rect srcRect, dstRect;

    if(scale) {
        // 得到最接近的值，且为16的倍数，而且只会比outputSize小
        mFirst = (outputSize.first / 16) * 16;
        mSecond = (mFirst * 9) / 16;
        if(mSecond > outputSize.second) {
            mSecond = (outputSize.second / 9) * 9;
            mFirst = (mSecond / 9) * 16;
        }
    }
    dstRect = {0, 0, (mFirst/2*2), (mSecond/2*2)};

    if(startPoint.first == 0 || startPoint.second == 0) {
        srcRect = {startPoint.first, startPoint.second, inputSize.first, inputSize.second};
    }
    else {
        if(((mFirst/2*2)+startPoint.first) > inputSize.first || ((mSecond/2*2)+startPoint.second) > inputSize.second) {

            std::cerr << "坐标不符合要求" << std::endl;
            return 1;
        }
        // nv12 中由于像素对齐的需求，扣图的时候，参数是2的倍数
        srcRect = {(startPoint.first/2*2), (startPoint.second/2*2), (mFirst/2*2), (mSecond/2*2)};
    }

    memset(&srcImg, 0, sizeof(srcImg));
    memset(&dstImg, 0, sizeof(dstImg));

    srcBufSize = inputSize.first * inputSize.second * get_bpp_from_format(fmtInput);
    dstBufSize = outputSize.first * outputSize.second * get_bpp_from_format(fmtOutput);

    dstBuf.clear();
    dstBuf.resize(dstBufSize, 0x80);
    srcHandle = importbuffer_virtualaddr(srcBuf.data(), srcBufSize);
    dstHandle = importbuffer_virtualaddr(dstBuf.data(), dstBufSize);
    if (srcHandle == 0 || dstHandle == 0) {

        ret = 1;
        goto RELEASE_HANDLE;
    }

    srcImg = wrapbuffer_handle(srcHandle, inputSize.first, inputSize.second, fmtInput);
    dstImg = wrapbuffer_handle(dstHandle, outputSize.first, outputSize.second, fmtOutput);

    ret = improcess(srcImg, dstImg, {}, srcRect, dstRect, {}, IM_SYNC);
    if(ret != IM_STATUS_SUCCESS) {

        ret = 1;
        goto RELEASE_HANDLE;
    }

    ret = 0;

RELEASE_HANDLE:
    if (srcHandle)
        releasebuffer_handle(srcHandle);
    if (dstHandle)
        releasebuffer_handle(dstHandle);

    return ret;
}

void RKRga::format_change(RgaSURF_FORMAT input, RgaSURF_FORMAT output)
{
    fmtInput = input;
    fmtOutput = output;
}

int RKRga::crop_auto(std::string &srcBuf, std::string &dstBuf, const std::pair<int32_t, int32_t> &inputSize, std::pair<int32_t, int32_t> &outputSize, int left, int top, int right, int bottom)
{
    // nv12 中由于像素对齐的需求，扣图的时候，x，y是2的倍数
    int dstWidth, dstHeight;
    left = (left/2*2);
    top = (top/2*2);
    dstWidth = (right - left)/2*2;
    dstHeight = (bottom - top)/2*2;
    if( dstWidth> inputSize.first
        || dstHeight > inputSize.second
        || dstWidth < 0
        || dstHeight < 0
        || inputSize.first < 128
        || inputSize.second < 67 ) {

        std::cerr << "点位不符合要求" << std::endl;
        return 1;
    }

    if(dstHeight < 67) {
        dstHeight = 67;
    }

    if(dstWidth < 128) {
        dstHeight = 128;
    }
    else if((dstWidth % 16) != 0) {
        int i = dstWidth / 16;
        dstWidth = 16 * (i+1);
        if(dstWidth > inputSize.first) {
            dstWidth = 16 * (i-1);
        }
    }
    outputSize = {dstWidth, dstHeight};

    int ret = 0;
    int srcBufSize, dstBufSize;
    rga_buffer_t srcImg, dstImg;
    im_rect srcRect, dstRect;
    rga_buffer_handle_t srcHandle, dstHandle;

    memset(&srcImg, 0, sizeof(srcImg));
    memset(&dstImg, 0, sizeof(dstImg));
    memset(&srcRect, 0, sizeof(srcRect));
    memset(&dstRect, 0, sizeof(dstRect));

    srcBufSize = inputSize.first * inputSize.second * get_bpp_from_format(cropfmtInput);
    dstBufSize = dstWidth * dstHeight * get_bpp_from_format(cropfmtOutput);

    dstBuf.clear();
    dstBuf.resize(dstBufSize, 0x80);
    srcHandle = importbuffer_virtualaddr(srcBuf.data(), srcBufSize);
    dstHandle = importbuffer_virtualaddr(dstBuf.data(), dstBufSize);
    if (srcHandle == 0 || dstHandle == 0) {

        ret = 1;
        goto RELEASE_HANDLE;
    }

    srcImg = wrapbuffer_handle(srcHandle, inputSize.first, inputSize.second, cropfmtInput);
    dstImg = wrapbuffer_handle(dstHandle, dstWidth, dstHeight, cropfmtOutput);

    srcRect = {left, top, dstWidth, dstHeight};
    dstRect = {0, 0, dstWidth, dstHeight};

    ret = improcess(srcImg, dstImg, {}, srcRect, dstRect, {}, IM_SYNC);
    if(IM_STATUS_SUCCESS != ret) {

        ret = 1;
        goto RELEASE_HANDLE;
    }

    ret = 0;

RELEASE_HANDLE:
    if (srcHandle)
        releasebuffer_handle(srcHandle);
    if (dstHandle)
        releasebuffer_handle(dstHandle);

    return ret;
}

void RKRga::crop_fmt_change(RgaSURF_FORMAT input, RgaSURF_FORMAT output)
{
    cropfmtInput = input;
    cropfmtOutput = output;
}

